﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using Assist;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Controls;
using YArchitech.LIB;
using YArchitech.Revit;

namespace YArchitech.HVAC
{
	[Transaction(TransactionMode.Manual)]
	[Regeneration(RegenerationOption.Manual)]
	public class DirectAutoRoundBeam : IExternalCommand
	{
		[DllImport("user32.dll", EntryPoint = "SendMessageA")]
		public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

		private bool hasElbow(Element elem)
		{
			bool result = true;
			if (elem is Pipe)
			{
				RoutingPreferenceManager routingPreferenceManager = (elem as Pipe).PipeType.RoutingPreferenceManager;
				try
				{
					if (!(elem.Document.GetElementById((elem as Pipe).PipeType.RoutingPreferenceManager.GetRule((Autodesk.Revit.DB.RoutingPreferenceRuleGroupType)1, 0).MEPPartId) is FamilySymbol))
					{
						result = false;
					}
					return result;
				}
				catch
				{
					return false;
				}
			}
			if (elem is Duct)
			{
				RoutingPreferenceManager routingPreferenceManager2 = (elem as Duct).DuctType.RoutingPreferenceManager;
				try
				{
					if (!(elem.Document.GetElementById((elem as Duct).DuctType.RoutingPreferenceManager.GetRule((Autodesk.Revit.DB.RoutingPreferenceRuleGroupType)1, 0).MEPPartId) is FamilySymbol))
					{
						result = false;
					}
					return result;
				}
				catch
				{
					return false;
				}
			}
			if (elem is Conduit)
			{
				if (!(elem.Document.GetElementById(elem.Document.GetElementById((elem as Conduit).get_Parameter(BuiltInParameter.ELEM_FAMILY_PARAM).AsElementId()).get_Parameter(BuiltInParameter.RBS_CURVETYPE_DEFAULT_BEND_PARAM).AsElementId()) is FamilySymbol))
				{
					result = false;
				}
			}
			else if (elem is CableTray && !(elem.Document.GetElementById(elem.Document.GetElementById((elem as CableTray).get_Parameter(BuiltInParameter.ELEM_FAMILY_PARAM).AsElementId()).get_Parameter(BuiltInParameter.RBS_CURVETYPE_DEFAULT_HORIZONTAL_BEND_PARAM).AsElementId()) is FamilySymbol))
			{
				result = false;
			}
			return result;
		}

		public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
		{
			Transaction transaction = null;
			if (commandData == null)
			{
				throw new NotImplementedException();
			}
			UIDocument activeUIDocument = commandData.Application.ActiveUIDocument;
			Document document = activeUIDocument.Document;
			Selection selection = activeUIDocument.Selection;
			List<ViewType> viewTypes = YJKRevitTools.ListViewNeed(2);
			if (!YJKRevitTools.ViewCheck(activeUIDocument, viewTypes))
			{
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			FormAllLineLength formAllLineLength = new FormAllLineLength(true);
			Result result;
			try
			{
				if (DirectAutoRoundBeam.hWndRevit == null)
				{
					DirectAutoRoundBeam.hWndRevit = new YJKWindowHandle(Process.GetCurrentProcess().MainWindowHandle);
				}
				formAllLineLength.Show(DirectAutoRoundBeam.hWndRevit);
				int wMsg = 7;
				DirectAutoRoundBeam.SendMessage(DirectAutoRoundBeam.hWndRevit.Handle, wMsg, IntPtr.Zero, IntPtr.Zero);
				RevitVersionFuncs.ClearSelection(selection);
				string text = "直接升降";
				transaction = new Transaction(document, text);
				transaction.Start();
				IList<Element> list = new List<Element>();
				new List<Duct>();
				ISelectionFilter selectionFilter = new PipingSJPYSelectionFilter();
				for (;;)
				{
					try
					{
						list = selection.PickElementsByRectangle(selectionFilter, "请框选要自动避让的风管,水管,线管，桥架");
						if (list.Count < 1)
						{
							YJKMessageBox.Information("没有选中任何实体，请重新选择！");
							continue;
						}
						Element element = null;
						Element element2 = null;
						bool flag = false;
						XYZ xyz = null;
						for (int i = 0; i < list.Count; i++)
						{
							for (int j = 1; j < list.Count; j++)
							{
								if (YJKRevitTools.IsElementIntersectsElement(list.ElementAt(i), list.ElementAt(j)))
								{
									element = list.ElementAt(i);
									element2 = list.ElementAt(j);
									flag = true;
									Line line = (element.Location as LocationCurve).Curve as Line;
									Line line2 = (element2.Location as LocationCurve).Curve as Line;
									xyz = new YJKLine(line).IntersectionPoint(YJKRevitTools.getIntersectLine(line, line2));
									break;
								}
							}
							if (flag)
							{
								break;
							}
						}
						if (element != null && element2 != null && element.Id != element2.Id && xyz != null)
						{
							Element sjelem = this.getSJElem(element, element2);
							Element elem = null;
							if (sjelem.Id != element.Id)
							{
								elem = element;
							}
							else if (sjelem.Id != element2.Id)
							{
								elem = element2;
							}
							double num = 3.0;
							double num2 = 4.5;
							this.getDiameterOrHeight(elem);
							double diameterOrWitdh = this.getDiameterOrWitdh(elem);
							double num3 = this.getDiameterOrHeight(elem) + num * this.getDiameterOrHeight(sjelem);
							this.getDiameterOrWitdh(elem);
							this.getDiameterOrWitdh(sjelem);
							double distance = 0.0;
							double num4 = 0.0;
							double num5 = Math.PI*.5;
							IList<XYZ> source = new List<XYZ>();
							if (num5 == Math.PI*.5)
							{
								distance = diameterOrWitdh + num * this.getDiameterOrHeight(sjelem);
								num4 = ((num3 - num2 * this.getDiameterOrHeight(sjelem) > 0.01) ? num3 : (num2 * this.getDiameterOrHeight(sjelem)));
							}
							if (!formAllLineLength.isUp)
							{
								num4 = 0.0 - num4;
							}
                            YArchitech.Revit.YJKLine hyline = new YArchitech.Revit.YJKLine((sjelem.Location as LocationCurve).Curve as Line);
							double z = hyline.EndPoint.Z;
							source = hyline.GetLineXYZList(new XYZ(xyz.X, xyz.Y, z), distance);
							if (hyline.IsPointOnLine(source.ElementAt(0)) && hyline.IsPointOnLine(source.ElementAt(1)))
							{
								if (!this.hasElbow(sjelem))
								{
									YJKMessageBox.Show("请先在管道连接配置中弯头一栏添加弯头族！");
									break;
								}
								if (sjelem is Pipe)
								{
									Pipe pipe = sjelem as Pipe;
									new HYPipeConnect().NewPipePIANYI(pipe, source.ElementAt(0), source.ElementAt(1), num4, num5, "升降", true);
								}
								else if (sjelem is Duct)
								{
									Duct pipe2 = sjelem as Duct;
									new HYDuctAlignment().NewPipePIANYI(pipe2, source.ElementAt(0), source.ElementAt(1), num4, num5, "升降", true);
								}
								else if (sjelem is Conduit)
								{
									num4 = 12.0 * (sjelem as Conduit).Diameter;
									if (!formAllLineLength.isUp)
									{
										num4 = 0.0 - num4;
									}
									source = hyline.GetLineXYZList(new XYZ(xyz.X, xyz.Y, z), 8.0 * (sjelem as Conduit).Diameter);
									Conduit pipe3 = sjelem as Conduit;
									new HYCableTrayRoundBeam().NewPipePIANYI(pipe3, source.ElementAt(0), source.ElementAt(1), num4, num5, "升降", true);
								}
								else if (sjelem is CableTray)
								{
									num4 = 6.0 * this.getDiameterOrHeight(sjelem as CableTray);
									if (!formAllLineLength.isUp)
									{
										num4 = 0.0 - num4;
									}
									CableTray pipe4 = sjelem as CableTray;
									new HYCableTrayRoundBeam().NewPipePIANYI(pipe4, source.ElementAt(0), source.ElementAt(1), num4, num5, "升降", true);
								}
							}
							else
							{
								YJKMessageBox.Show("要升降的管道过短，无法升降！");
							}
						}
						else
						{
							YJKMessageBox.Show("所框选的实体中没有相互碰撞的，请重新选择！");
						}
						continue;
					}
					catch (Autodesk.Revit.Exceptions.OperationCanceledException)
					{
					}
					break;
				}
				formAllLineLength.Close();
				transaction.Commit();
				result = Autodesk.Revit.UI.Result.Succeeded;
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException)
			{
				formAllLineLength.Close();
				result = Autodesk.Revit.UI.Result.Succeeded;
			}
			catch (Exception ex)
			{
				formAllLineLength.Close();
				message = ex.Message;
				result = Autodesk.Revit.UI.Result.Failed;
			}
			finally
			{
				if (1 == (int)transaction.GetStatus())
				{
					formAllLineLength.Close();
					transaction.RollBack();
				}
			}
			return result;
		}

		private bool isTs(Element elem1)
		{
			bool result = false;
			if (elem1 is Pipe)
			{
				string text = (elem1 as Pipe).get_Parameter(BuiltInParameter.RBS_PIPING_SYSTEM_TYPE_PARAM).AsValueString();
				if (text != null && ((text.Contains("污水") && !text.Contains("压力")) || (text.Contains("废水") && !text.Contains("压力")) || (text.Contains("排水") && !text.Contains("压力")) || (text.Contains("雨水") && !text.Contains("虹吸") && !text.Contains("压力"))))
				{
					result = true;
				}
			}
			return result;
		}

		private double getDiameterOrWitdh(Element elem)
		{
			double result = 0.0;
			if (elem is Pipe)
			{
				result = new YJKPiping<Pipe>(elem as Pipe).GetDiameter();
			}
			else if (elem is Duct)
			{
				result = new YJKPiping<Duct>(elem as Duct).GetDiameter();
			}
			if (elem is Conduit)
			{
				result = (elem as Conduit).GetParameter(BuiltInParameter.RBS_CONDUIT_DIAMETER_PARAM).AsDouble();
			}
			else if (elem is CableTray)
			{
				result = (elem as CableTray).GetParameter(BuiltInParameter.RBS_CABLETRAY_WIDTH_PARAM).AsDouble();
			}
			return result;
		}

		private double getDiameterOrHeight(Element elem)
		{
			double result = 0.0;
			if (elem is Pipe)
			{
				result = new YJKPiping<Pipe>(elem as Pipe).GetDiameter();
			}
			else if (elem is Duct)
			{
				result = new YJKPiping<Duct>(elem as Duct).GetHeightOrDiameter();
			}
			if (elem is Conduit)
			{
				result = (elem as Conduit).GetParameter(BuiltInParameter.RBS_CONDUIT_DIAMETER_PARAM).AsDouble();
			}
			else if (elem is CableTray)
			{
				result = (elem as CableTray).GetParameter(BuiltInParameter.RBS_CABLETRAY_HEIGHT_PARAM).AsDouble();
			}
			return result;
		}

		private Element getSJElem(Element elem1, Element elem2)
		{
			double diameterOrWitdh = this.getDiameterOrWitdh(elem1);
			double diameterOrWitdh2 = this.getDiameterOrWitdh(elem2);
			Element result = null;
			if (this.isTs(elem1) && this.isTs(elem2))
			{
				if (diameterOrWitdh < diameterOrWitdh2)
				{
					result = elem1;
				}
				else
				{
					result = elem2;
				}
			}
			else if (this.isTs(elem1) && !this.isTs(elem2))
			{
				result = elem2;
			}
			else if (!this.isTs(elem1) && this.isTs(elem2))
			{
				result = elem1;
			}
			else if (!this.isTs(elem1) && !this.isTs(elem2))
			{
				if (diameterOrWitdh < diameterOrWitdh2)
				{
					result = elem1;
				}
				else
				{
					result = elem2;
				}
			}
			return result;
		}

		public static YJKWindowHandle hWndRevit;
	}
}
